package com.zzl.bonds.ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.bonds.ticket.constant.CreditDataStatusEnum;
import com.zzl.bonds.ticket.constant.StringConstant;
import com.zzl.bonds.ticket.constant.UserCategoryConstant;
import com.zzl.bonds.ticket.constant.status.CreditStatusEnum;
import com.zzl.bonds.ticket.constant.status.FrozenStatusEnum;
import com.zzl.bonds.ticket.constant.type.CreditTypeEnum;
import com.zzl.bonds.ticket.constant.type.CreditUseTypeEnum;
import com.zzl.bonds.ticket.constant.type.QuotaTypeEnum;
import com.zzl.bonds.ticket.dao.SupplierCreditDao;
import com.zzl.bonds.ticket.dto.credit.BwBankAddDto;
import com.zzl.bonds.ticket.dto.credit.SupplierAvailableCreditDto;
import com.zzl.bonds.ticket.dto.feign.FinanceInstitutyEntity;
import com.zzl.bonds.ticket.dto.finance.*;
import com.zzl.bonds.ticket.entity.EnterpriseCreditDataEntity;
import com.zzl.bonds.ticket.entity.SupplierCreditEntity;
import com.zzl.bonds.ticket.entity.TicketFinanceEntity;
import com.zzl.bonds.ticket.entity.TicketOpenEntity;
import com.zzl.bonds.ticket.exception.SysExceptionFactory;
import com.zzl.bonds.ticket.feign.BaseDataFeign;
import com.zzl.bonds.ticket.service.CoreEnterpriseCredidataService;
import com.zzl.bonds.ticket.service.CoreEnterpriseCreditService;
import com.zzl.bonds.ticket.service.SupplierCreditService;
import com.zzl.bonds.ticket.service.common.TicketFinanceHandService;
import com.zzl.general.common.constant.Constant;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.feign.dto.Enterprise;
import com.zzl.general.common.requestparameter.StringIds;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.PageUtils;
import com.zzl.general.common.utils.QmBeanUtils;
import com.zzl.general.common.utils.Query;
import com.zzl.general.common.utils.UuidUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.zzl.bonds.ticket.exception.SysExceptionEnum.*;

/**
 * 供应商授信额度表,即集团给供应商的额度
 *
 * @author sunpp
 * @date 2022-02-16 14:04:04
 */
@Slf4j
@Service("supplierCreditService")
public class SupplierCreditServiceImpl extends ServiceImpl<SupplierCreditDao, SupplierCreditEntity> implements SupplierCreditService {

    @Autowired
    private CoreEnterpriseCreditService coreEnterpriseCreditService;
    @Autowired
    private CoreEnterpriseCredidataService coreEnterpriseCredidataService;
    @Autowired
    private TicketFinanceHandService ticketFinanceHandService;
    @Autowired
    private BaseDataFeign baseDataFeign;

    /**
     * 回滚 供应商额度
     *
     * @param enterpriseId 供应商id
     * @param amount       金额
     * @param instityId    金融机构id
     * @param user         登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void rollBackSupplierCredit(String enterpriseId, Double amount, String instityId, User user) throws SysException {
        log.info("回滚 供应商额度{}{}{}", enterpriseId, amount, instityId);
        QueryWrapper<SupplierCreditEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SupplierCreditEntity::getReceiveEnterpriseId, enterpriseId)
                .eq(SupplierCreditEntity::getInstitutyId, instityId)
                .eq(SupplierCreditEntity::getLatestStatus, CreditDataStatusEnum.LATEST.getCode());
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            throw new SysException("回滚供应商额度，未找到");
        }
        SupplierCreditEntity entity = list.get(0);
        entity.setCreditAvailableAmount(entity.getCreditAvailableAmount() + amount);
        entity.setCreditFrozenAmount(entity.getCreditFrozenAmount() - amount);
        this.updateById(entity);
    }

    /**
     * 扣减额度
     *
     * @param openEntity 开立实体
     * @param user       登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void reduceSupplierCredit(TicketOpenEntity openEntity, User user) throws SysException {
        log.info("扣减额度:{}", JSON.toJSONString(openEntity));
        QueryWrapper<SupplierCreditEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SupplierCreditEntity::getInstitutyId, openEntity.getInstinctyId())
                .eq(SupplierCreditEntity::getReceiveEnterpriseId, openEntity.getReceiveEnterpriseId())
                .eq(SupplierCreditEntity::getLatestStatus, CreditDataStatusEnum.LATEST.getCode());
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            throw new SysException("未找到当前签收方的开票额度");
        }
        SupplierCreditEntity supplierCredit = list.get(0);
        supplierCredit.setUpdaterId(user.getId());
        supplierCredit.setCreditSurplusAmount(supplierCredit.getCreditSurplusAmount() - openEntity.getTicketAmount());
        supplierCredit.setCreditFrozenAmount(supplierCredit.getCreditFrozenAmount() - openEntity.getTicketAmount());
        this.updateById(supplierCredit);
    }

    /**
     * 可给当前供应商在某金融机构开票额度
     * 2022/1/21 新增确认逻辑
     * 1。  如果未查到 则展示金融机构的授信额度
     * 2. 金融机构的 授信额度 如果 小于 给该企业的 开票额度 则展示金融机构的开票额度
     *
     * @param enterpriseId       供应商id
     * @param financeInstitutyId 金融机构id
     * @param coreCreditId       授信类型
     * @param user               登录用户
     * @return 供应商在金融机构的 可用授信额度
     * @throws SysException 业务异常
     */
    @Override
    public SupplierAvailableCreditDto availableCredit(String enterpriseId, Integer financeInstitutyId, String coreCreditId, User user) throws SysException {
        SupplierAvailableCreditDto result = new SupplierAvailableCreditDto();
        /*TODO*/
        double available = 0.0;
        Double coreAvailableAmount = coreEnterpriseCreditService.getCoreAvailableAmount(coreCreditId);
        result.setAvailableAmount(available <= coreAvailableAmount ? available : coreAvailableAmount);
        return result;
    }


    /**
     * 新增或者 修改 供应商的 开票额度
     * 1. 如果传入的 供应商的开票额度id 则进行 更新 然后新增
     * 2. 否则 进行新增
     *
     * @param bankShowDtos 参数集合
     * @param user         登录用户
     * @throws SysException 业务衣异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAndSaveSupplierCredit(List<BwBankAddDto> bankShowDtos, User user) throws SysException {
        //参数校验
        verifyBankShowDtos(bankShowDtos);
        log.info("新增或者修改供应商的开票额度{}", JSON.toJSONString(bankShowDtos));


        //1、处理老数据的修改
        List<BwBankAddDto> updateList = bankShowDtos.stream().filter(x -> !ObjectUtils.isEmpty(x.getId())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(updateList)) {
            // 设置为 历史 数据
            List<String> updateIds = updateList.stream().map(BwBankAddDto::getId).distinct().collect(Collectors.toList());
            LambdaUpdateWrapper<SupplierCreditEntity> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.in(SupplierCreditEntity::getId, updateIds)
                    // 设置历史数据
                    .set(SupplierCreditEntity::getLatestStatus, 0);
            this.update(updateWrapper);

            // 新增新的数据
            Collection<SupplierCreditEntity> creditEntities = this.listByIds(updateIds);
            for (SupplierCreditEntity creditEntity : creditEntities) {
                creditEntity.setLatestStatus(1);
                creditEntity.setQuotaType(QuotaTypeEnum.QUOTA_TYPE_VOUCHER_FINANCING.getCode());
                //  新增的 总额度
                // 修改融资限额，后续剩余可用额度也跟着改变。
                //计算方式：剩余可用额度=融资限额-在途额度
                Optional<BwBankAddDto> first = updateList.stream().filter(dto -> dto.getId().equals(creditEntity.getId())).findFirst();
                if (first.isPresent()) {
                    BwBankAddDto bwBankAddDto = first.get();
                    //无额度限制时，置空原来额度
                    if (bwBankAddDto.getCreditLimitFlag()) {
                        creditEntity.setCreditSurplusAmount(null);
                        creditEntity.setCreditAllAmount(null);
                        creditEntity.setCreditFrozenAmount(0.0);
                        creditEntity.setCreditUsedAmount(creditEntity.getCreditUsedAmount());
                        creditEntity.setCreditAvailableAmount(0.0);
                    } else {
                        creditEntity.setCreditAllAmount(bwBankAddDto.getCreditAllAmount());
                        creditEntity.setCreditSurplusAmount(bwBankAddDto.getCreditAllAmount() - creditEntity.getCreditUsedAmount());
                        creditEntity.setCreditAvailableAmount(bwBankAddDto.getCreditAllAmount() - creditEntity.getCreditAllAmount() + creditEntity.getCreditAvailableAmount());
                    }


                }
                creditEntity.setUpdaterId(user.getId());
                creditEntity.setId(UuidUtils.UUID());
                creditEntity.setCreatorId(user.getId());
            }
            // 批量保存
            this.saveBatch(creditEntities);
        }
        //2、处理新数据的新增
        // 新增 金融机构的 开票额度 过滤出金额不为 空的
        List<BwBankAddDto> saveList = bankShowDtos.stream().filter(x -> ObjectUtils.isEmpty(x.getId())
                && !ObjectUtils.isEmpty(x.getCreditAllAmount())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(saveList)) {
            List<String> receiveIds = saveList.stream().map(BwBankAddDto::getReceiveEnterpriseId).collect(Collectors.toList());
            receiveIds.add("1");
            List<Enterprise> enterPriseByIds = baseDataFeign.getEnterPriseByIds(new StringIds(receiveIds));
            // 找到所有的 金融机构的名称
            AtomicReference<String> coreEnterpriseName = new AtomicReference<>("");
            enterPriseByIds.stream().filter(x -> x.getId().equals(1)).findFirst().ifPresent(
                    p -> coreEnterpriseName.set(p.getEnterpriseName())
            );
            List<FinanceInstitutyEntity> financeInstitutyEntities = baseDataFeign.listFinanceInstituty();
            List<SupplierCreditEntity> supplierCreditEntities = QmBeanUtils.copyListProperties(saveList, SupplierCreditEntity::new);
            Date date = new Date();
            supplierCreditEntities.forEach(x -> {
                x.setId(UuidUtils.UUID());
                x.setCreditNo(UuidUtils.UUID());
                //无额度限制时，置空原来额度
                x.setCreditSurplusAmount(x.getCreditAllAmount());
                x.setCreditFrozenAmount(0.0);
                x.setCreditUsedAmount(0.0);
                x.setCreditAvailableAmount(x.getCreditAllAmount());

                x.setCreatorId(user.getId());
                x.setLatestStatus(1);

                x.setQuotaType(QuotaTypeEnum.QUOTA_TYPE_VOUCHER_FINANCING.getCode());
                // 登录用户的 企业id 默认集团
                x.setCreditEnterpriseId(user.getEnterpriseId());
                x.setCreditEnterpriseName(coreEnterpriseName.get());
                if (!CollectionUtils.isEmpty(enterPriseByIds)) {
                    enterPriseByIds.stream().filter(e -> e.getId().equals(x.getReceiveEnterpriseId())).findFirst().ifPresent(
                            p -> x.setReceiveEnterpriseName(p.getEnterpriseName()));
                }
                if (!CollectionUtils.isEmpty(financeInstitutyEntities)) {
                    financeInstitutyEntities.stream().filter(f -> f.getId().equals(x.getInstitutyId())).findFirst().ifPresent(
                            p -> x.setInstitutyName(p.getInstinctyName())
                    );
                }
                x.setPlatFrozenStatus(0);
                x.setCreateTime(date);
                x.setEnterpriseId(user.getEnterpriseId());
            });
            this.saveBatch(supplierCreditEntities);
        }
    }


    /**
     * 校验前端传入的 数据
     *
     * @param bankShowDtos 数据对象
     * @throws SysException 业务异常
     */
    private void verifyBankShowDtos(List<BwBankAddDto> bankShowDtos) throws SysException {
        if (CollectionUtils.isEmpty(bankShowDtos)) {
            return;
        }
        // 验证 对于一家供应商的 开票额度 其 金融机构的 id 应该是不同的
        List<String> list = bankShowDtos.stream().map(BwBankAddDto::getInstitutyId).collect(Collectors.toList());
        List<String> distinct = list.stream().distinct().collect(Collectors.toList());
        if (list.size() != distinct.size()) {
            throw new SysException("修改的 供应商额度 所在的金融机构 参数错误，存在重复值");
        }
        for (BwBankAddDto bankShowDto : bankShowDtos) {
            if (!ObjectUtils.isEmpty(bankShowDto.getCreditAllAmount()) && bankShowDto.getCreditAllAmount() > 100000000000000d) {
                throw new SysException("额度总额数量太大");
            }
        }
    }

    /**
     * 分页查询
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SupplierCreditEntity> page = this.page(
                new Query<SupplierCreditEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    /**
     * 新增
     *
     * @param supplierCreditAddDto 新增实体
     * @param user                 当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void saveSupplierCredit(SupplierCreditAddDto supplierCreditAddDto, User user) throws SysException {
        SupplierCreditEntity supplierCreditEntity = new SupplierCreditEntity();
        BeanUtils.copyProperties(supplierCreditAddDto, supplierCreditEntity);
        supplierCreditEntity.setCreatorId(user.getId());
        if (!this.save(supplierCreditEntity)) {
            throw new SysException("A00001", "保存失败！");
        }
    }

    /**
     * 修改
     *
     * @param supplierCreditUpdateDto 修改实体
     * @param user                    当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void updateSupplierCreditById(SupplierCreditUpdateDto supplierCreditUpdateDto, User user) throws SysException {
        SupplierCreditEntity supplierCreditEntity = new SupplierCreditEntity();
        BeanUtils.copyProperties(supplierCreditUpdateDto, supplierCreditEntity);
        supplierCreditEntity.setUpdaterId(user.getId());
        if (!this.updateById(supplierCreditEntity)) {
            throw new SysException("A00002", "修改失败！");
        }
    }

    /**
     * 根据企业id 查找授信额度 以及在 各个金融机构的额度
     *
     * @param receiverEnterPriseIds 接收授信额度的企业id 集合
     * @return 返回map key 是企业id value 是 该企业的 信用额度
     */
    @Override
    public Map<String, List<SupplierCreditEntity>> getEnterpriseQuota(List<String> receiverEnterPriseIds) {
        // 最近的信用数据
        LambdaQueryWrapper<SupplierCreditEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 接收企业id
        queryWrapper.in(SupplierCreditEntity::getReceiveEnterpriseId, receiverEnterPriseIds)
                .eq(SupplierCreditEntity::getQuotaType, QuotaTypeEnum.QUOTA_TYPE_VOUCHER_FINANCING.getCode())
                // 最新数据
                .eq(SupplierCreditEntity::getLatestStatus, 1);
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        // 根据 企业id 分组
        return list.stream().collect(Collectors.groupingBy(SupplierCreditEntity::getReceiveEnterpriseId));
    }

    /**
     * 将某个 供应商的 可融资总额度 恢复到最初始的 可额度
     *
     * @param enterpriseId 供应商id
     * @param user         登录用户
     */
    @Override
    public void resetSupplierCredit(String enterpriseId, User user) throws SysException {
        //校验当前供应商id 是否存在
        LambdaQueryWrapper<SupplierCreditEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SupplierCreditEntity::getReceiveEnterpriseId, enterpriseId)
                .eq(SupplierCreditEntity::getQuotaType, QuotaTypeEnum.QUOTA_TYPE_VOUCHER_FINANCING.getCode())
                .eq(SupplierCreditEntity::getLatestStatus, 1);
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 最新的 数据中 该企业的可开票额度未查到 则给出提示
            throw new SysException("未查到该企业的在金融机构中的可用开票额度！");
        }
        this.baseMapper.resetSupplierCredit(enterpriseId, null, user.getId());
    }

    /**
     * 新增融资额度
     *
     * @param supplierCreditAddDto 融资额度信息
     * @param user                 用户
     */
    @Override
    public void addFinanceCredit(SupplierCreditAddDto supplierCreditAddDto, User user) throws SysException {
        if (FrozenStatusEnum.FROZEN_STATUS_YES.getCode().equals(supplierCreditAddDto.getLockStatus())
                && null == supplierCreditAddDto.getCreditLockAmount()) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_AMOUNT_ERROR);
        }
        //一个金融机构只能添加一个融资授信
        this.checkSupplierCredit(supplierCreditAddDto);
        SupplierCreditEntity supplierCreditEntity = new SupplierCreditEntity();
        BeanUtils.copyProperties(supplierCreditAddDto, supplierCreditEntity);
        supplierCreditEntity.setCreditEnterpriseId(user.getEnterpriseId());
        supplierCreditEntity.setCreatorId(user.getId());
        supplierCreditEntity.setUpdaterId(user.getId());
        supplierCreditEntity.setLatestStatus(CreditDataStatusEnum.LATEST.getCode());
//        supplierCreditEntity.setCreditUseType(CreditUseTypeEnum.FINANCE_CREDIT.getCode());
        //设置可用授信额度
        Double creditAllAmount = supplierCreditAddDto.getCreditAllAmount();
        Double creditLockAmount = supplierCreditAddDto.getCreditLockAmount();
        Double availableAmount = (null == creditLockAmount ? creditAllAmount : creditAllAmount - creditLockAmount);
        supplierCreditEntity.setCreditAvailableAmount(availableAmount);
        supplierCreditEntity.setCreditSurplusAmount(supplierCreditAddDto.getCreditAllAmount());
        //设置企业名称
        this.setEnterpriseName(user, supplierCreditEntity);
        //设置金融机构名称
        this.setFinanceInstitutyName(supplierCreditEntity);


        //设置授信状态
        Date nowDate = new Date();
        if (nowDate.before(supplierCreditAddDto.getEffectTime())) {
            supplierCreditEntity.setCreditStatus(CreditStatusEnum.NOT_EFFECTIVE.getCode());
        } else if (nowDate.after(supplierCreditAddDto.getExpireTime())) {
            supplierCreditEntity.setCreditStatus(CreditStatusEnum.FAIL.getCode());
        } else {
            supplierCreditEntity.setCreditStatus(CreditStatusEnum.SUCCESS.getCode());
        }
        if (!this.save(supplierCreditEntity)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_SAVE_ERROR);
        }
        List<EnterpriseCreditDataEntity> files = supplierCreditAddDto.getDatas();
        // 新增 授信的资料
        coreEnterpriseCredidataService.addCreditDatas(files, supplierCreditEntity.getId(), user);

    }

    /**
     * 一个金融机构只能添加一个融资授信
     *
     * @param supplierCreditAddDto 融资授信
     */
    private void checkSupplierCredit(SupplierCreditAddDto supplierCreditAddDto) throws SysException {
        QueryWrapper<SupplierCreditEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SupplierCreditEntity::getInstitutyId, supplierCreditAddDto.getFinanceInstitutyId())
                .eq(SupplierCreditEntity::getReceiveEnterpriseId, supplierCreditAddDto.getReceiveEnterpriseId())
//                .eq(SupplierCreditEntity::getCreditUseType, CreditUseTypeEnum.FINANCE_CREDIT.getCode())
                .eq(SupplierCreditEntity::getCreditStatus, CreditDataStatusEnum.LATEST.getCode());
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_CHECK_ERROR);
        }
    }

    /**
     * 设置金融机构名称
     *
     * @param supplierCreditEntity
     */
    private void setFinanceInstitutyName(SupplierCreditEntity supplierCreditEntity) throws SysException {
        List<String> idList = new ArrayList<>();
        idList.add(supplierCreditEntity.getInstitutyId());
        StringIds ids = new StringIds();
        ids.setIds(idList);
        List<FinanceInstitutyEntity> financeInstitutyEntities = baseDataFeign.listFinanceInstitutyByIds(ids);
        if (CollectionUtils.isEmpty(financeInstitutyEntities) || financeInstitutyEntities.size() != 1) {
            throw new SysException("金融机构传入不正确");
        }
        FinanceInstitutyEntity financeInstitutyEntity = financeInstitutyEntities.get(0);
        supplierCreditEntity.setInstitutyName(financeInstitutyEntity.getInstinctyName());
    }

    /**
     * 设置企业名称
     *
     * @param user                 用户
     * @param supplierCreditEntity 额度授信
     */
    private void setEnterpriseName(User user, SupplierCreditEntity supplierCreditEntity) throws SysException {
        List<String> idList = new ArrayList<>();
        idList.add(supplierCreditEntity.getReceiveEnterpriseId());
        idList.add(user.getEnterpriseId());
        StringIds ids = new StringIds();
        ids.setIds(idList);
        List<Enterprise> enterPriseByIds = baseDataFeign.getEnterPriseByIds(ids);
        if (CollectionUtils.isEmpty(enterPriseByIds) || enterPriseByIds.size() != 2) {
            throw new SysException("额度授信主体不存在或已被删除！");
        }
        Map<String, String> collect = enterPriseByIds.stream().collect(Collectors.toMap(Enterprise::getId, Enterprise::getEnterpriseName));
        supplierCreditEntity.setCreditEnterpriseName(collect.get(user.getEnterpriseId()));
        supplierCreditEntity.setReceiveEnterpriseName(collect.get(supplierCreditEntity.getReceiveEnterpriseId()));
    }

    /**
     * 修改融资授信。不做修改操作，增加一条数据
     *
     * @param supplierCreditUpdateDto 融资授信
     * @param user                    用户
     */
    @Override
    public void updateFinanceCredit(SupplierCreditUpdateDto supplierCreditUpdateDto, User user) throws SysException {
        SupplierCreditEntity oldSupplierCredit = this.getById(supplierCreditUpdateDto.getId());
        oldSupplierCredit.setLatestStatus(CreditDataStatusEnum.HISTORY.getCode());
        oldSupplierCredit.setUpdaterId(user.getId());
        if (!this.updateById(oldSupplierCredit)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_UPDATE_ERROR);
        }

        SupplierCreditEntity supplierCreditEntity = new SupplierCreditEntity();
        BeanUtils.copyProperties(oldSupplierCredit, supplierCreditEntity);
        BeanUtils.copyProperties(supplierCreditUpdateDto, supplierCreditEntity);
        supplierCreditEntity.setCreditEnterpriseId(user.getEnterpriseId());
        supplierCreditEntity.setUpdaterId(user.getId());
        supplierCreditEntity.setLatestStatus(CreditDataStatusEnum.LATEST.getCode());
        //若修改了额度，则重新计算可用额度，剩余额度、冻结额度
        if (!oldSupplierCredit.getPlatFrozenAmount().equals(supplierCreditUpdateDto.getCreditLockAmount())
                || !oldSupplierCredit.getCreditAllAmount().equals(supplierCreditUpdateDto.getCreditAllAmount())) {
            supplierCreditEntity.setCreditSurplusAmount(supplierCreditUpdateDto.getCreditAllAmount());
            supplierCreditEntity.setCreditAvailableAmount(
                    supplierCreditUpdateDto.getCreditAllAmount() - supplierCreditUpdateDto.getCreditLockAmount() - supplierCreditEntity.getCreditFrozenAmount());
        }
        if (!this.save(supplierCreditEntity)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_UPDATE_ERROR);
        }
        List<EnterpriseCreditDataEntity> files = supplierCreditUpdateDto.getDatas();
        // 修改 授信的资料
        coreEnterpriseCredidataService.addCreditDatas(files, supplierCreditEntity.getId(), user);

    }

    /**
     * 分页查询授信额度
     *
     * @param params 条件筛选
     * @param user   用户
     * @return 融资授信列表
     */
    @Override
    public PageUtils querySupplierCreditPage(Map<String, Object> params, User user, HttpSession session) {

        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<SupplierCreditListDto> page = new Query<SupplierCreditListDto>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
        params.put("creditUseType", CreditUseTypeEnum.FINANCE_CREDIT.getCode());
        IPage<SupplierCreditListDto> resultPage = this.baseMapper.querySupplierCreditPage(page, params);
        List<SupplierCreditListDto> resultPageRecords = resultPage.getRecords();
        if (!CollectionUtils.isEmpty(resultPageRecords)) {
            ticketFinanceHandService.setFinanceCreditOperates(resultPageRecords, session);
        }
        return new PageUtils(resultPage);
    }

    /**
     * 融资额度详情
     *
     * @param id 融资额度id
     * @return 融资额度详情
     */
    @Override
    public SupplierCreditDetailDto getFinanceCredit(String id) {
        SupplierCreditDetailDto supplierCreditDetailDto = new SupplierCreditDetailDto();
        SupplierCreditEntity byId = this.getById(id);
        BeanUtils.copyProperties(byId, supplierCreditDetailDto);
        //附件资料
        List<EnterpriseCreditDataEntity> files = coreEnterpriseCredidataService.getCredidataBySupplierId(id, CreditTypeEnum.FINANCE_CREDIT.getCode());
        supplierCreditDetailDto.setDatas(files);
        return supplierCreditDetailDto;
    }

    /**
     * 查询融资额度列表
     *
     * @param user 用户
     * @return 融资额度列表
     */
    @Override
    public List<SupplierCreditEntity> getFinanceCreditList(User user) {
        QueryWrapper<SupplierCreditEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SupplierCreditEntity::getReceiveEnterpriseId, user.getEnterpriseId())
                .eq(SupplierCreditEntity::getQuotaType, QuotaTypeEnum.QUOTA_TYPE_VOUCHER_FINANCING.getCode())
                .eq(SupplierCreditEntity::getLatestStatus, CreditDataStatusEnum.LATEST.getCode());
        List<SupplierCreditEntity> list = this.list(queryWrapper);
        return list;
    }

    /**
     * 融资授信冻结扣减
     *
     * @param ticketFinanceAddDto 融资申请
     * @param user                用户
     */
    @Override
    public SupplierCreditEntity frozenFinanceSupplierCredit(TicketFinanceAddDto ticketFinanceAddDto, User user) throws SysException {
        String supplierCreditId = ticketFinanceAddDto.getSupplierCreditId();
        SupplierCreditEntity supplierCreditEntity = this.getById(supplierCreditId);
        if (ObjectUtils.isEmpty(supplierCreditEntity)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_NOT_FOUND_ERROR);
        }
        Double creditAvailableAmount = supplierCreditEntity.getCreditAvailableAmount();
        //可用额度校验
        if (creditAvailableAmount < ticketFinanceAddDto.getFinanceAmount()) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_AMOUNT_INSUFFICIENT_ERROR);
        }
        //额度扣减
        SupplierCreditEntity supplierCredit = new SupplierCreditEntity();
        supplierCredit.setId(supplierCreditEntity.getId());
        supplierCredit.setCreditAvailableAmount(supplierCreditEntity.getCreditAvailableAmount() - ticketFinanceAddDto.getTicketAmount());
        supplierCredit.setCreditFrozenAmount(supplierCreditEntity.getCreditFrozenAmount() + ticketFinanceAddDto.getTicketAmount());
        if (!this.updateById(supplierCredit)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_DEDUCTION_ERROR);
        }
        supplierCreditEntity.setCreditAvailableAmount(supplierCredit.getCreditAvailableAmount());
        supplierCreditEntity.setCreditFrozenAmount(supplierCredit.getCreditFrozenAmount());
        return supplierCreditEntity;
    }

    /**
     * 融资授信重置
     *
     * @param financeEntity 融资申请
     * @param user          用户
     */
    @Override
    public void resetFinanceSupplierCredit(TicketFinanceEntity financeEntity, User user) throws SysException {
        SupplierCreditEntity supplierCreditEntity = this.getById(financeEntity.getSupplierCreditId());
        //额度扣减
        SupplierCreditEntity supplierCredit = new SupplierCreditEntity();
        supplierCredit.setId(supplierCreditEntity.getId());
        supplierCredit.setCreditAvailableAmount(supplierCreditEntity.getCreditAvailableAmount() + financeEntity.getFinanceAmount());
        supplierCredit.setCreditFrozenAmount(supplierCreditEntity.getCreditFrozenAmount() - financeEntity.getFinanceAmount());
        if (!this.updateById(supplierCredit)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_DEDUCTION_ERROR);
        }
    }

    /**
     * 融资授信真实扣减
     *
     * @param financeEntity 融资申请
     * @param user          用户
     */
    @Override
    public void deductFinanceSupplierCredit(TicketFinanceEntity financeEntity, User user) throws SysException {
        SupplierCreditEntity supplierCreditEntity = this.getById(financeEntity.getSupplierCreditId());
        //额度扣减
        SupplierCreditEntity supplierCredit = new SupplierCreditEntity();
        supplierCredit.setId(supplierCreditEntity.getId());
        supplierCredit.setUpdaterId(user.getId());
        supplierCredit.setCreditSurplusAmount(supplierCreditEntity.getCreditSurplusAmount() - financeEntity.getFinanceAmount());
        supplierCredit.setCreditFrozenAmount(supplierCreditEntity.getCreditFrozenAmount() - financeEntity.getFinanceAmount());
        if (!this.updateById(supplierCredit)) {
            throw SysExceptionFactory.createSysException(TICKET_CREDIT_FINANCE_DEDUCTION_ERROR);
        }
    }

    /**
     * 重置融资额度
     *
     * @param id   融资额度id
     * @param user 用户id
     */
    @Override
    public void resetFinancingCredit(String id, User user) throws SysException {
        SupplierCreditEntity byId = this.getById(id);
        if (ObjectUtils.isEmpty(byId)) {
            throw new SysException("当前融资额度不存在");
        }
        this.baseMapper.resetSupplierCredit(null, id, user.getId());
    }
}